import base64
import io
import socket

import cv2
import numpy as np

from django.forms import model_to_dict
from PIL import Image


def get_lan_ip():
    """
    获取本机局域网ip
    :return: ip地址
    """
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        s.connect(('8.8.8.8', 80))
        ip = s.getsockname()[0]
        return ip
    finally:
        s.close()


def get_user_dict(user) -> dict:
    user_dict = model_to_dict(user, exclude=['password'])
    user_dict['avatar'] = str(user.avatar)
    user_dict['date_joined'] = user.date_joined.strftime('%Y-%m-%d %H:%M:%S')
    return user_dict


def beautify_dict(target_dict, func_dict=None, default=None):
    """
    根据指定的处理函数美化字典
    :param target_dict: 目标字典
    :param func_dict: 处理函数字典，按照键对应的函数处理值
    :param default: 默认处理函数，处理上面未处理的值
    :return: 返回美化后的新字典
    """
    result_dict = {}
    func_dict = func_dict or {}
    default = default or (lambda x: x)
    for k, v in target_dict.items():
        fn = func_dict.get(k)
        if fn:
            result_dict[k] = fn(v)
        else:
            result = default(v)
            if result is None:
                pass
            else:
                result_dict[k] = result
    return result_dict


def format_datetime(datetime):
    """
    将日期时间类型格式化为YYYY-mm-dd HH:MM:SS格式的字符串
    :param datetime: 日期时间
    :return: 返回格式化后的字符串
    """
    return datetime.strftime('%Y-%m-%d %H:%M:%S') if datetime else ''


def format_date(date):
    """
    将日期类型格式化为YYYY-mm-dd格式的字符串
    :param date: 日期
    :return: 返回格式化后的字符串
    """
    return date.strftime('%Y-%m-%d') if date else ''


def get_int(s: str, default: int = None) -> int:
    """
    将一个字符串转为int类型数值
    :param s: 目标字符串
    :param default: 目标字符串无法转为int时的默认值
    :return: 返回一个int或者None
    """
    if type(s) is not str:
        return default
    if s.isdigit():
        return int(s)
    return default


def base64_to_cv_image(base64_code):
    """
    将base64编码的图片转为cv2可以使用的nparray数据
    :param base64_code: 图片的base64编码
    :return: 返回cv2图片数据
    """
    # base64解码
    img_bytes = base64.b64decode(base64_code)

    # 将bytes转换为np数组
    # img_array = np.array(bytearray(img_bytes), np.uint8)
    img_array = np.fromstring(img_bytes, np.uint8)

    # 转换成opencv可用格式
    img = cv2.imdecode(img_array, cv2.COLOR_RGB2BGR)
    return img


def base64_to_rgb_array(base64_code: str, resize: int = None):
    """
    使用PIL将base64编码的图片转为RGB格式的nparray数据
    :param base64_code: 图片的base64编码
    :param resize: 短边缩放后的尺寸
    :return: 返回RGB格式的nparray数据
    """
    # base64解码
    img_bytes = base64.b64decode(base64_code)

    # 将bytes转换为io对象
    img_io = io.BytesIO(img_bytes)

    # PIL打开该图片的io对象
    img_pil = Image.open(img_io)
    # img_pil = img_pil.convert('RGB')  # 默认就是RGB，此行可以注释掉

    # 短边缩放
    if resize is not None:
        w, h = img_pil.size
        if w < h:
            rate = (resize, int(resize / w * h))
        else:
            rate = (int(resize / h * w), resize)
        img_pil = img_pil.resize(rate)

    # 转换成nparray格式并返回
    return np.array(img_pil)
